﻿using CrossFlow.GraphLib;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;

namespace DependencyLib
{
    //http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.graphmodel(v=vs.110).aspx
    public class DigraphAsDGMLWriter
    {
        const string ns = "http://schemas.microsoft.com/vs/2009/dgml";

        private XmlDocument dgml;
        private XmlNamespaceManager names;
        public DigraphAsDGMLWriter()
        {
            Stream stream = this.GetType().Assembly.GetManifestResourceStream("DependencyLib.template.dgmlRoot.xml");
            using (StreamReader reader = new StreamReader(stream))
            {
                dgml = new XmlDocument();
                dgml.Load(reader);
            }

            names = new XmlNamespaceManager(this.dgml.NameTable);
            names.AddNamespace("vs", ns);
        }

        public void Write(TextWriter writer, DirectedGraph graph)
        {
            foreach (Vertex vertex in graph.Vertexes)
            {
                AddVertex(vertex);
            }
            foreach (Edge edge in graph.Edges)
            {
                AddLink(edge);
            }
            Save(writer);
        }

        private void AddVertex(Vertex vertex)
        {
            XmlElement newvertex = this.dgml.CreateElement("vs:Node", ns);
            XmlAttribute id = this.dgml.CreateAttribute("Id");
            newvertex.Attributes.Append(id);
            id.Value = vertex.Name;

            XmlNode nodes = this.dgml.SelectSingleNode("/vs:DirectedGraph/vs:Nodes", this.names);
            nodes.AppendChild(newvertex);
        }

        private void AddLink(Edge edge)
        {
            XmlElement newlink = this.dgml.CreateElement("vs:Link", ns);
            XmlAttribute source = this.dgml.CreateAttribute("Source");
            newlink.Attributes.Append(source);
            source.Value = edge.Source.Name;
            XmlAttribute target = this.dgml.CreateAttribute("Target");
            newlink.Attributes.Append(target);
            target.Value = edge.Target.Name;

            XmlNode links = this.dgml.SelectSingleNode("/vs:DirectedGraph/vs:Links", this.names);
            links.AppendChild(newlink);
        }

        public void Save(TextWriter writer)
        {
            var settings = new XmlWriterSettings();
            settings.NamespaceHandling = NamespaceHandling.OmitDuplicates;
            var xmlwriter = XmlTextWriter.Create(writer, settings);
            this.dgml.Save(xmlwriter);
        }
    }
}